package me.hetong.caigou;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import javafx.application.Platform;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.media.AudioClip;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import me.hetong.caigou.engine.UciEngine;
import me.hetong.caigou.entity.Qipu;
import me.hetong.caigou.ui.chessboard.ChessBoardWar;
import me.hetong.caigou.ui.pane.PaneCommon;
import me.hetong.caigou.ui.stage.EditJuStage;
import me.hetong.caigou.ui.stage.IndexStage;
import me.hetong.caigou.ui.view.Infer;
import me.hetong.caigou.ui.view.LineChartWebView;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.MultiResolutionImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 全局工具类
 */
public class Global {

    /**
     * 应用目录
     */
    public static String homePath = System.getProperty("user.home").concat("/titi/caigou/");
    public static String tempPath = homePath.concat("temp/");
    public static String configPath = homePath.concat("config.json");
    public static String logsPath = homePath.concat("logs/");
    private static final Robot ROBOT;

    /**
     * 当前打开的棋谱
     */
    public static Qipu qipu;
    public static Config config;
    public static UciEngine engine;

    public static AudioClip MOVE_AUDIO;
    public static AudioClip BACK_AUDIO;
    public static AudioClip ERROR_AUDIO;
    public static AudioClip APP_STARTUP_AUDIO;
    private static double oldScreenX;
    private static double oldScreenY;
    private static double oldStageX;
    private static double oldStageY;

    static {

        new File(Global.homePath).mkdirs();
        new File(Global.tempPath).mkdirs();

        if (FileUtil.exist(configPath)) {
            config = JSONUtil.toBean(FileUtil.readUtf8String(configPath), Config.class);
        } else {
            config = new Config();
            FileUtil.writeUtf8String(config.toString(), configPath);
        }

        engine = new UciEngine(config.getEnginePath());

        String string = Thread.currentThread().getContextClassLoader().getResource("").toString();
        MOVE_AUDIO = new AudioClip(string + "sound/drop.wav");
        BACK_AUDIO = new AudioClip(string + "sound/back.wav");
        ERROR_AUDIO = new AudioClip(string + "sound/error.wav");
        APP_STARTUP_AUDIO = new AudioClip(string + "sound/app_startup.wav");

        playSound(APP_STARTUP_AUDIO);

        try {
            ROBOT = new Robot();
        } catch (AWTException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 注册快捷键
     *
     * @param scene
     */
    public static void shortcutKeys(Scene scene) {
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.LEFT), ChessBoardWar::prev);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.RIGHT), ChessBoardWar::next);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.UP), ChessBoardWar::begin);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.DOWN), ChessBoardWar::end);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.SPACE), ChessBoardWar::inferModel);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.A), Infer::doInfer);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.C), () -> EditJuStage.init(null));
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.E), () -> engine.startUp());
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.M), () -> Global.snapshot(PaneCommon.InferPane));
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.O), Global::openWen);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.P), Infer::pastDongping);
        scene.getAccelerators().put(new KeyCodeCombination(KeyCode.S), Global::saveWen);
    }

    /**
     * 播放音效
     *
     * @param audioClip
     */
    public static void playSound(AudioClip audioClip) {
        if (config.isSoundPlay()) {
            Platform.runLater(() -> {
                ThreadUtil.execute(audioClip::play);
            });
        }
    }

    public static void saveWen() {
        if (qipu != null) {

            if (CollUtil.isEmpty(qipu.getZhaoList()) && CollUtil.isEmpty(ChessBoardWar.inferList)) {
                IndexStage.VIEW.getMessageBean().info("保存失败,没有有效着法");
            }

            if (StrUtil.isBlank(qipu.getPath())) {
                FileChooser fileChooser = new FileChooser();
                fileChooser.setInitialFileName(qipu.getTitle().concat(qipu.getRed()).concat(qipu.getResult()).concat(qipu.getBlack()).concat(".qipu"));
                File file = fileChooser.showSaveDialog(new Stage());

                if (file == null) {
                    IndexStage.VIEW.getMessageBean().info("取消保存");
                    return;
                }


                qipu.setPath(file.getAbsolutePath());
            }

            FileUtil.writeUtf8String(qipu.toString(), qipu.getPath());
            IndexStage.VIEW.getMessageBean().info("保存成功", qipu.getPath());
        } else {
            IndexStage.VIEW.getMessageBean().info("保存失败,棋谱为空");
        }
    }

    public static void openWen() {

        FileChooser fileChooser = new FileChooser();
        fileChooser.getExtensionFilters().add(
                new FileChooser.ExtensionFilter("菜狗象棋棋谱", "*.qipu")
        );

        File file = fileChooser.showOpenDialog(new Stage());
        if (file == null) {
            return;
        }

        String s = FileUtil.readUtf8String(file.getAbsolutePath());
        loadWen(s);
    }

    public static void loadWen(String s) {
        qipu = JSONUtil.toBean(s, Qipu.class);

        PaneCommon.matchInfoLabel.setText(qipu.getTitle().concat(" ").concat(qipu.getRedTeam()).concat(qipu.getRed()).concat(" ").concat(qipu.getBlackTeam()) + qipu.getBlack());
        Infer.chessboardForEngine.setChessList(qipu.getZhaoList().get(0).getFen1());
        Infer.chessboardForEngine.setZhao1(null);
        Infer.chessboardForEngine.setZhao2(null);
        Infer.chessboardForEngine.setZhao3(null);
        Infer.chessboardForEngine.setZhao4(null);
        Infer.chessboardForEngine.setZhao(null);
        ChessBoardWar.begin();
        ChessBoardWar.isInfering = false;
        ChessBoardWar.inferList = new ArrayList<>();
        LineChartWebView.transFromMatchData();
        StaticLog.info("打开棋谱", qipu);
    }

    public static AnchorPane createRightBox(Pane pane) {

        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().add(pane);

        int width = config.getLeftWidth() + config.getRightWidth();
        int height = config.getHeight();

        anchorPane.setPrefSize(width, height);
        anchorPane.setMaxSize(width, height);
        anchorPane.setMinSize(width, height);

        pane.setStyle("-fx-background-color: linear-gradient(to top, #0b7f8b, #008474, #398551, #67812b, #94760c);");
        pane.setPrefSize(width, height);
        pane.setMaxSize(width, height);
        pane.setMinSize(width, height);

        return anchorPane;
    }

    /**
     * 添加窗口右键按住拖动事件监听
     *
     * @param stage
     */
    public static void rightMouseDrag(Stage stage) {
        Scene scene = stage.getScene();
        scene.setOnMousePressed(event -> {
            if (event.getButton().equals(MouseButton.SECONDARY)) {
                oldStageX = stage.getX();
                oldStageY = stage.getY();
                oldScreenX = event.getScreenX();
                oldScreenY = event.getScreenY();
            }
        });

        scene.setOnMouseDragged(event -> {
            //新位置
            //拖拽前后的鼠标差值加上原始窗体坐标值
            if (event.getButton().equals(MouseButton.SECONDARY)) {
                stage.setX(event.getScreenX() - oldScreenX + oldStageX);
                stage.setY(event.getScreenY() - oldScreenY + oldStageY);
            }
        });
    }

    /**
     * 截图
     *
     * @param pane
     * @return
     */
    public static BufferedImage snapshot(Pane pane) {
        Bounds bounds = pane.localToScreen(pane.getLayoutBounds());
        Rectangle rectangle = new Rectangle((int) bounds.getMinX(), (int) bounds.getMinY(), (int) pane.getWidth(), (int) pane.getHeight());

        MultiResolutionImage screenCapture = ROBOT.createMultiResolutionScreenCapture(rectangle);
        List<Image> resolutionVariants = screenCapture.getResolutionVariants();

        try {
            BufferedImage bufferedImage = (BufferedImage) resolutionVariants.get(1);
            String path = tempPath.concat(System.currentTimeMillis() + "").concat(".png");
            ImageIO.write(bufferedImage, "png", new File(path));

            IndexStage.VIEW.getMessageBean().info("截图成功", path);
            return bufferedImage;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}